//////////////////////////////////////////////////////////////////////
////                                                              ////
////  CFDecoder.v                                                 ////
////                                                              ////
////                                                              ////
////  This file is part of the "Pico E12" project                 ////
////  http://www.picocomputing.com                                ////
////                                                              ////
////                                                              ////
//////////////////////////////////////////////////////////////////////
////                                                              ////
//// Copyright (C) 2005, Picocomputing, Inc.                      ////
//// http://www.picocomputing.com/                                ////
////                                                              ////
////////////////////////////////////////////////////////////////////JF

`timescale 10ns / 1ps
`include "PicoDefines.v"

module CFDecoder(
                CLOCK1,
                CLOCK2,
                CFClock,
                DCM_KEEPER,
                CE1_DIRTY,
                CE2_DIRTY,
                REG,
                IORD,
                IOWR, 
                OE,
                WE,                                    
                READY,    
                WP_IOIS16,
                INPACK, 
                BVD1,   
                BVD2,                                
                CF_ADDRESSDIR,
                CF_CTRLDIR, 
                CF_DATADIRH, 
                CF_DATADIRL,
                CF_DATATRISH,
                CF_DATATRISL,
                DIN,
                DOUT,
                A,

                DataIn,
                DataOut,
                MemAddress,
                IOAddress,
                MemRead,
                MemWrite,
                AttribRead,
                AttribWrite,
                IORead,
                IOWrite,
                ByteMode
);

input           CLOCK1;
input           CLOCK2;
output          CFClock;
output          DCM_KEEPER;
input           CE1_DIRTY;                                 //The CE signals must be cleaned up due to some poor PCMCIA implimentations
input           CE2_DIRTY;
input           REG;
input           IORD;
input           IOWR; 
input           OE;
input           WE;                                    
output          READY;    
output          WP_IOIS16;
output          INPACK; 
output          BVD1;   
output          BVD2;  
output          CF_ADDRESSDIR;
output          CF_CTRLDIR; 
output          CF_DATADIRH; 
output          CF_DATADIRL;
output          CF_DATATRISH;
output          CF_DATATRISL;
input           [15:0]DIN;
output          [15:0]DOUT;
input           [10:0]A;

output          [15:0]DataIn;
input           [15:0]DataOut;
output          [31:0]MemAddress;
output          [`PCMCIA_ADR_LINES-1:0]IOAddress;
output          MemRead;
output          MemWrite;
output          AttribRead;
output          AttribWrite;
output          IORead;
output          IOWrite;
output          ByteMode;


wire            CFClock;
wire            CE1_DIRTY;
wire            CE2_DIRTY;
wire            REG;
wire            REG_CLEAN;
wire            IORD;
wire            IORD_CLEAN;
wire            IOWR; 
wire            IOWR_CLEAN;
wire            OE;
wire            OE_CLEAN;
wire            WE;      
wire            WE_CLEAN;                              
wire            READY;    
wire            WP_IOIS16;
wire            INPACK; 
wire            BVD1;   
wire            BVD2;  
wire            CF_ADDRESSDIR;
wire            CF_CTRLDIR; 
wire            CF_DATADIRH; 
wire            CF_DATADIRL;
wire            [15:0]DIN;
wire            [15:0]DOUT;
wire            [10:0]A;

wire            [15:0]DataIn;
wire            [15:0]DataOut;
wire            [31:0]MemAddress;
wire            [`PCMCIA_ADR_LINES-1:0]IOAddress;
wire            MemRead;
wire            MemWrite;
wire            AttribRead;
wire            AttribWrite;
wire            IORead;
wire            IOWrite;
wire            ByteMode;

wire            CE1;
wire            CE2;

wire CardEnabled;
wire MasterRead;

wire MemReadLatch;
wire IOWriteLatch;
wire MemWriteLatch;
wire WriteLatch;
wire MemReadHold;
wire IOReadLatch;
wire IOReadHold;

wire ReadLatch;
wire ReadHold;

wire [15:0]AddressDecoderDataOut;
wire [15:0]DatabusDecoderDataOut;
wire [15:0]CFCORDataOut;

assign READY = 1;
assign BVD1 = 1;
assign BVD2 = 1;
assign CF_ADDRESSDIR    = 0;
assign CF_CTRLDIR = 1;
assign CF_DATADIRH = (MasterRead) && (~CE2);                                             //This logic ensures that the PCMCIA output databus will be driven
assign CF_DATADIRL = (MasterRead) && (~CE1);                                             //as soon as data is requested. A floating bus is not allowed.
assign CardEnabled = ((~CE1) || (~CE2));

ShortFallingDelay DATA_DIR_H_TRIS(.Clock(CFClock), .In(~CF_DATADIRH), .Out(CF_DATATRISH));  //Delaying the falling edge of a Tristate signal ensures there are no transient bus conflicts 
ShortFallingDelay DATA_DIR_L_TRIS(.Clock(CFClock), .In(~CF_DATADIRL), .Out(CF_DATATRISL));  //which appear to result in single bit upsets in the V4 architecture

assign WriteLatch = (IOWriteLatch) || (MemWriteLatch);
assign ReadLatch = (MemReadLatch) || (IOReadLatch);
assign ReadHold = (MemReadHold) || (IOReadHold);
assign MasterRead = (ReadLatch) || (ReadHold);

//200 MHz Clock Generator
CFClockGen CFClockGen(.CLOCKIN(CLOCK1), .ClockOut(CFClock));

//These module cleans up glitchy signals
CFCECleaner CFCECleaner(.CFClock(CFClock), .CE1_DIRTY(CE1_DIRTY), .CE2_DIRTY(CE2_DIRTY), .OE(OE), .WE(WE), .IORD(IORD), .IOWR(IOWR), .CE1(CE1), .CE2(CE2));
CFClean CFClean_REG(.CFClock(CFClock), .In(REG), .Out(REG_CLEAN));
CFClean CFClean_OE(.CFClock(CFClock), .In(OE), .Out(OE_CLEAN));
CFClean CFClean_WE(.CFClock(CFClock), .In(WE), .Out(WE_CLEAN));
CFClean CFClean_IORD(.CFClock(CFClock), .In(IORD), .Out(IORD_CLEAN));
CFClean CFClean_IOWR(.CFClock(CFClock), .In(IOWR), .Out(IOWR_CLEAN));

//This is the master databus that ends up at the host in the end.                                                
assign DatabusDecoderDataOut[15:0] = (AddressDecoderDataOut[15:0] | DataOut[15:0] | CFCORDataOut[15:0]);

//This module detects if the card is getting accesses in 8 bit mode
CFByteMode CFByteMode(.CFClock(CFClock), .CE1(CE1), .CE2(CE2), .ByteMode(ByteMode));

//This module latches the PCMCIA databus to extend write cycle time. This also ensures that valid data is on DataIn and DataOut for the maximum amount of time.
CFDatabusDecoder CFDatabusDecoder(.CE1(CE1), .CE2(CE2), .A0(A[0]), .DIN(DIN[15:0]), .DOUT(DOUT[15:0]),
    .ReadLatch(ReadLatch), .WriteLatch(WriteLatch), .DataIn(DataIn[15:0]), .DataOut(DatabusDecoderDataOut[15:0]));

//This module detects memory and attribute reads
CFMemRead CFMemRead(.CFClock(CFClock), .CardEnabled(CardEnabled), .OE(OE_CLEAN), .WE(WE_CLEAN), .IORD(IORD_CLEAN), .IOWR(IOWR_CLEAN), .REG(REG_CLEAN),
    .MemReadLatch(MemReadLatch), .MemRead(MemRead), .AttribRead(AttribRead), .MemReadHold(MemReadHold));

//This module detects memory and attribute writes
CFMemWrite CFMemWrite(.CFClock(CFClock), .CardEnabled(CardEnabled), .OE(OE_CLEAN), .WE(WE_CLEAN), .IORD(IORD_CLEAN), .IOWR(IOWR_CLEAN), .REG(REG_CLEAN), 
    .MemWrite(MemWrite), .AttribWrite(AttribWrite), .MemWriteLatch(MemWriteLatch));

//This module detects IO reads
CFIORead CFIORead(.CFClock(CFClock), .CardEnabled(CardEnabled), .OE(OE_CLEAN), .WE(WE_CLEAN), .IORD(IORD_CLEAN), .IOWR(IOWR_CLEAN), .REG(REG_CLEAN),
                   .IOReadLatch(IOReadLatch), .IORead(IORead), .IOReadHold(IOReadHold));

//This module detects IO writes
CFIOWrite CFIOWrite(.CFClock(CFClock), .CardEnabled(CardEnabled), .OE(OE_CLEAN), .WE(WE_CLEAN), .IORD(IORD_CLEAN), .IOWR(IOWR_CLEAN), .REG(REG_CLEAN), 
                     .IOWriteLatch(IOWriteLatch), .IOWrite(IOWrite));

//This module latches the address bus when not in use. It also impliments the address extension registers.
CFAddressDecoder CFAddressDecoder(.CFClock(CFClock), .CardEnabled(CardEnabled), .A(A[10:0]), .REG(REG_CLEAN), .OE(OE_CLEAN), .WE(WE_CLEAN), .IORD(IORD_CLEAN), .IOWR(IOWR_CLEAN), .INPACK(INPACK), .IOIS16(WP_IOIS16), 
    .IORead(IORead),    .IOWrite(IOWrite), .AttribRead(AttribRead), .AttribWrite(AttribWrite), 
     .MemAddress(MemAddress[31:0]), .IOAddress(IOAddress[`PCMCIA_ADR_LINES-1:0]), .DataIn(DataIn[15:0]), 
     .DataOut(AddressDecoderDataOut[15:0]));


//This module controls the configuration option registers
//Memory address extebsions are controlled directly by the address decoder
CFCOR CFCOR(.AttribRead(AttribRead), .AttribWrite(AttribWrite), .A(A[10:1]), 
    .DataIn(DataIn[7:0]), .DataOut(CFCORDataOut[15:0]));



//These modules keep engineering sample silicon running at peak performance - removal voids warranty

wire VccAuxFixKeep;         //Certain synthesis tools optimize away modules that don't have external outputs - this signal is routed to an unconnected output pin
//synthesis attribute KEEP of VccAuxFixKeep is TRUE;


//VccAuxFix fixes an excessive power consumption bug with LX silicon and provides the startup clock (DO NOT REMOVE)
VccAuxFix VccAuxFix (.clk_in(CLOCK2), .busy(VccAuxFixKeep));

//Debug taps for ChipScope Pro
`ifdef ENABLE_DEBUG_TAPS
wire CE1_CLEAN_TAP;
wire CE2_CLEAN_TAP;
wire REG_CLEAN_TAP;
wire OE_CLEAN_TAP;
wire WE_CLEAN_TAP;
wire IORD_CLEAN_TAP;
wire IOWR_CLEAN_TAP;

//synthesis attribute KEEP of CE1_CLEAN_TAP is TRUE;
//synthesis attribute KEEP of CE2_CLEAN_TAP is TRUE;
//synthesis attribute KEEP of REG_CLEAN_TAP is TRUE;
//synthesis attribute KEEP of OE_CLEAN_TAP is TRUE;
//synthesis attribute KEEP of WE_CLEAN_TAP is TRUE;
//synthesis attribute KEEP of IORD_CLEAN_TAP is TRUE;
//synthesis attribute KEEP of IOWR_CLEAN_TAP is TRUE;

BUF CE1CleanBuffer(.I(CE1), .O(CE1_CLEAN_TAP));
BUF CE2CleanBuffer(.I(CE2), .O(CE2_CLEAN_TAP));
BUF REGCleanBuffer(.I(REG_CLEAN), .O(REG_CLEAN_TAP));
BUF OECleanBuffer(.I(OE_CLEAN), .O(OE_CLEAN_TAP));
BUF WECleanBuffer(.I(WE_CLEAN), .O(WE_CLEAN_TAP));
BUF IORDCleanBuffer(.I(IORD_CLEAN), .O(IORD_CLEAN_TAP));
BUF IOWRCleanBuffer(.I(IOWR_CLEAN), .O(IOWR_CLEAN_TAP));

`endif

endmodule